/*
Esempio 5.
Creazione di grafo e scrittura su file in formato DIMACS clique/coloring.
Lettura da file creato, riordino topologico ed esplorazione del grafo.

Grafo con 6 nodi e 5 archi:
1 2
2 3
2 4
2 5
5 6
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "glpk.h"

typedef struct { int num; } v_data;

#define vertex(v) ((v_data *)((v)->data))

int timeval_subtract(struct timeval *result, struct timeval *t2, struct timeval *t1)
{
    long int diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec);
    result->tv_sec = diff / 1000000;
    result->tv_usec = diff % 1000000;

    return (diff<0);
}

void timeval_print(struct timeval *tv)
{
    char buffer[30];
    time_t curtime;

    printf("%ld.%06ld", tv->tv_sec, tv->tv_usec);
    curtime = tv->tv_sec;
    strftime(buffer, 30, "%m-%d-%Y  %T", localtime(&curtime));
    printf(" = %s.%06ld\n", buffer, tv->tv_usec);
}

int main(void) {
	glp_graph *G, *G1;
	int i, cycles;
  struct timeval tvBegin, tvEnd, tvDiff;

  // Inizio operazioni
  gettimeofday(&tvBegin, NULL);
  
	// Inizializzazione grafi
	G = glp_create_graph(sizeof(v_data), 0);
	G1 = glp_create_graph(sizeof(v_data), 0);
	printf("\n");
	
	// Creazione primo grafo
	glp_add_vertices(G, 6);

	glp_add_arc(G, 1, 2);
	glp_add_arc(G, 2, 3);
	glp_add_arc(G, 2, 4);
	glp_add_arc(G, 2, 5);
	glp_add_arc(G, 5, 6);
	
	// Scrittura su file in formato DIMACS clique/coloring
	glp_write_ccdata(G, -1, "graph-example5.col");
		
	// Cancellazione primo grafo
	glp_delete_graph(G);
	
	// Creazione (da file) del secondo grafo
	glp_read_ccdata(G1, -1, "graph-example5.col");
	
	// Riordino numerico della topologia dei vertici e
	// calcolo (con visualizzazione) del numero di cicli presenti nel grafo
	cycles = glp_top_sort(G1, offsetof(v_data, num));
	printf("This graph has %d cycles.\n", cycles);

	// Visualizzazione nuova topologia
	printf("Topologia aggiornata dopo glp_top_sort():\n");
	for (i = 1; i <= G1->nv; i++)
		printf("num[%d] = %d\n", i, vertex(G1->v[i])->num);
	printf("\n");

	// Cancellazione secondo grafo
  glp_delete_graph(G1);
  
  // Fine operazioni
  gettimeofday(&tvEnd, NULL);
  
  // Calcolo e stampa del tempo trascorso
  timeval_subtract(&tvDiff, &tvEnd, &tvBegin);
  printf("Elapsed time: %ld.%06ld\n", tvDiff.tv_sec, tvDiff.tv_usec);
  
	return 0;
}